package controller

import (
	"demos/config"
	"demos/model"
	"demos/service"
	"demos/utils"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
)

// LoginRequest 登录请求结构体
type LoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// Login 登录接口
func Login(c *gin.Context) {
	var req LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}
	ok, role, userId := service.CheckLoginWithID(req.Username, req.Password)
	if !ok {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
		return
	}
	token, err := utils.GenerateToken(req.Username, role, userId)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "生成token失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "token": token})
}

// GetUsers 获取用户列表
func GetUsers(c *gin.Context) {
	// 分页、搜索、排序
	pageStr := c.DefaultQuery("page", "1")
	pageSizeStr := c.DefaultQuery("pageSize", "10")
	username := c.Query("username")
	email := c.Query("email")
	sortField := c.DefaultQuery("sortField", "id")
	sortOrder := c.DefaultQuery("sortOrder", "descend")
	page, _ := strconv.Atoi(pageStr)
	pageSize, _ := strconv.Atoi(pageSizeStr)
	var users []model.User
	db := config.DB
	if username != "" {
		db = db.Where("username LIKE ?", "%"+username+"%")
	}
	if email != "" {
		db = db.Where("email LIKE ?", "%"+email+"%")
	}
	order := sortField + " "
	if sortOrder == "ascend" {
		order += "asc"
	} else {
		order += "desc"
	}
	db = db.Order(order).Offset((page - 1) * pageSize).Limit(pageSize)
	db.Find(&users)
	var total int64
	config.DB.Model(&model.User{}).Count(&total)
	totalPage := (total + int64(pageSize) - 1) / int64(pageSize)
	c.JSON(http.StatusOK, gin.H{
		"code":      0,
		"data":      users,
		"total":     total,
		"page":      page,
		"pageSize":  pageSize,
		"totalPage": totalPage,
	})
}

// CreateUser 创建用户
func CreateUser(c *gin.Context) {
	var user model.User
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}
	if user.Username == "" || user.Email == "" || user.Password == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "用户名、邮箱和密码为必填"})
		return
	}
	// 用户名查重
	var count int64
	config.DB.Model(&model.User{}).Where("username = ?", user.Username).Count(&count)
	if count > 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "用户名已存在"})
		return
	}
	// 邮箱查重
	config.DB.Model(&model.User{}).Where("email = ?", user.Email).Count(&count)
	if count > 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "邮箱已存在"})
		return
	}
	if err := config.DB.Create(&user).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建失败"})
		return
	}
	// 发送邮件
	err := utils.SendMail(
		user.Email,
		"账号创建成功",
		"您的初始密码为："+user.Password+"，请及时修改密码。",
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "邮件发送失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0})
}

// UpdateUser 更新用户
func UpdateUser(c *gin.Context) {
	id := c.Param("id")
	var user model.User
	if err := config.DB.First(&user, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
		return
	}
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}
	user.Username = req.Username
	user.Email = req.Email
	user.Role = req.Role
	user.Status = req.Status
	if req.Password != "" {
		user.Password = req.Password
	}
	if err := config.DB.Save(&user).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": user})
}

// DeleteUser 删除用户
func DeleteUser(c *gin.Context) {
	id := c.Param("id")
	if err := config.DB.Delete(&model.User{}, id).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"msg": "删除成功"})
}

// Logout 退出登录接口
func Logout(c *gin.Context) {
	// 退出登录，前端丢弃token即可
	c.JSON(200, gin.H{"msg": "退出登录成功"})
}

// GetCurrentUser 获取当前登录用户信息
func GetCurrentUser(c *gin.Context) {
	username, _ := c.Get("username")
	var user model.User
	if err := config.DB.Where("username = ?", username).First(&user).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
		return
	}
	user.Password = ""
	c.JSON(http.StatusOK, gin.H{"code": 0, "data": user})
}

// UpdateCurrentUser 修改当前用户个人信息（允许修改用户名和密码，用户名和邮箱需查重）
func UpdateCurrentUser(c *gin.Context) {
	username, _ := c.Get("username")
	var user model.User
	if err := config.DB.Where("username = ?", username).First(&user).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
		return
	}
	var req struct {
		Username string `json:"username"`
		Email    string `json:"email"`
		Role     string `json:"role"`
		Status   string `json:"status"`
		Password string `json:"password"`
		Avatar   string `json:"avatar"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}
	// 用户名查重（排除自己）
	if req.Username != "" && req.Username != user.Username {
		var count int64
		config.DB.Model(&model.User{}).Where("username = ? AND id != ?", req.Username, user.ID).Count(&count)
		if count > 0 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "用户名已存在"})
			return
		}
		user.Username = req.Username
	}
	// 邮箱查重（排除自己）
	if req.Email != "" && req.Email != user.Email {
		var count int64
		config.DB.Model(&model.User{}).Where("email = ? AND id != ?", req.Email, user.ID).Count(&count)
		if count > 0 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "邮箱已存在"})
			return
		}
		user.Email = req.Email
	}
	if req.Role != "" {
		user.Role = req.Role
	}
	if req.Status != "" {
		user.Status = req.Status
	}
	if req.Password != "" {
		user.Password = req.Password
	}
	if req.Avatar != "" {
		user.Avatar = req.Avatar
	}
	if err := config.DB.Save(&user).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "data": user})
}

// CheckOldPassword 确认旧密码是否正确
func CheckOldPassword(c *gin.Context) {
	username, _ := c.Get("username")
	var req struct {
		OldPassword string `json:"oldPassword"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}
	var user model.User
	if err := config.DB.Where("username = ?", username).First(&user).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
		return
	}
	if user.Password != req.OldPassword {
		c.JSON(http.StatusOK, gin.H{"code": 1, "msg": "旧密码错误"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "旧密码正确"})
}
